package com.hd123.rumba.gwt.widget2.client.grid;

import java.util.List;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * 分页表格数据提供者
 * <p>
 * 由表格的使用者从此类派生，提供给RGrid使用。派生类需要实现两个方法：
 * <li>{@link #doFetch(int, AsyncCallback)}
 * ，在doFetch的实现中，派生类要执行RPC调用，注意<b>RPC的返回值应为 {@link RPageData}
 * 类型</b>。RPC调用需要的每页记录数可调用{@link #getPageSize()}
 * 获得，RPC调用的回调可直接使用doFetch的参数callback。例如：
 * 
 * <pre>
 * public void doFetch(int page, AsyncCallback callback) {
 *   Sample.getService().getProductList(page, getPageSize(), callback);
 * }
 * </pre>
 * 
 * <li>{@link #getData(int, int)}，在getData的实现中，派生类可调用
 * {@link #getValues()}获得数据，这些数据就是在doFetch中从RPC调用中返回的
 * {@link RPageData#getValues()}
 * 。其内容可以放置某B对象的列表，也可放置一个Object数据的列表，派生类可自由决定。
 * <p>
 * B对象列表的例子：
 * 
 * <pre>
 * public Object getData(int row, int col) {
 *   BProduct product = (BProduct) getValues().get(row);
 *   if (col == codeCol.getIndex())
 *     return product.getCode();
 *   else if (col == nameCol.getIndex())
 *     return product.getName();
 *   else
 *     return null;
 * }
 * </pre>
 * 
 * 对象数组的例子：
 * 
 * <pre>
 * public Object getData(int row, int col) {
 *   Object[] data = (Object[]) getValues().get(row);
 *   if (col == codeCol.getIndex())
 *     return data[0];
 *   else if (col == nameCol.getIndex())
 *     return data[1];
 *   else
 *     return null;
 * }
 * </pre>
 * 
 * 
 * @author LiQi
 * 
 */
public abstract class RGridPageDataProvider implements RGridDataProvider {

  /** 默认每页记录数 */
  public static final int DEFAULT_PAGE_SIZE = 20;

  /** 每页记录数 */
  private int pageSize = DEFAULT_PAGE_SIZE;

  /** 是否需要再次获取数据 */
  private boolean needFetch = true;

  /** 来自服务端的原始数据 */
  private RPageData rawData;

  public RGridPageDataProvider() {

  }

  /**
   * 执行获取数据动作<br>
   * 派生类通常应在此方法的实现中远程调用自己的服务端方法获取数据，这个远程调用的返回值类型应为RPageData
   * 
   * @param page
   *          当前页序号，从0计数
   * @param callback
   *          派生类可直接把callback作为自己的远程调用的回调
   */
  public abstract void doFetch(int page, AsyncCallback<RPageData> callback);

  /**
   * 总记录数
   * 
   * @return
   */
  public int getTotalCount() {
    return rawData == null ? 0 : rawData.getTotalCount();
  }

  /**
   * 总页数
   * 
   * @return
   */
  public int getPageCount() {
    return rawData == null ? 0 : rawData.getPageCount();
  }

  /**
   * 当前页序号，从0计数
   * 
   * @return
   */
  public int getCurrentPage() {
    return rawData == null ? 0 : rawData.getCurrentPage();
  }

  /**
   * 当前页记录数
   * 
   * @see com.hd123.rumba.gwt.widget2.client.grid.RGridDataProvider#getRowCount()
   */
  public int getRowCount() {
    return rawData == null ? 0 : rawData.getValues().size();
  }

  /**
   * 每页记录数
   * 
   * @return
   */
  public int getPageSize() {
    return pageSize;
  }

  /**
   * 设置每页记录数
   * 
   * @param pageSize
   */
  public void setPageSize(int pageSize) {
    this.pageSize = pageSize;
  }

  /**
   * 当前页数据
   * 
   * @return
   */
  public List getValues() {
    return rawData == null ? null : rawData.getValues();
  }

  /**
   * 设置是否需要再次获取数据
   * 
   * @param needFetch
   */
  public void setNeedFetch(boolean needFetch) {
    this.needFetch = needFetch;
  }

  /**
   * 获取数据
   * 
   * @param page
   *          当前页序号，从0计数
   * @param callback
   *          获取数据结果的回调，回调返回值类型为Boolean，表示是否需要刷新表格显示
   */
  public void fetch(final int page, final AsyncCallback callback) {
    if (needFetch || page != getCurrentPage()) {
      doFetch(page, new AsyncCallback<RPageData>() {
        public void onFailure(Throwable caught) {
          callback.onFailure(caught);
        }

        public void onSuccess(RPageData result) {
          rawData = result;
          callback.onSuccess(Boolean.TRUE); // 刷新表格显示
          setNeedFetch(false);
        }
      });
    } else {
      callback.onSuccess(Boolean.FALSE); // 不需要刷新表格显示
    }
  }

}
